package com.lvy.hczn.front.business.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lvy.hczn.front.business.common.Constants;
import com.lvy.hczn.front.business.dto.Param;
import com.lvy.hczn.front.business.service.*;
import com.lvy.hczn.front.common.exception.UtilException;
import com.lvy.hczn.front.framework.web.domain.server.Sys;
import com.lvy.hczn.front.quartz.domain.SysJobLog;
import com.lvy.hczn.front.quartz.service.ISysJobLogService;
import com.lvy.hczn.front.system.domain.business.*;
import com.lvy.hczn.front.system.domain.system.SysOperLog;
import com.lvy.hczn.front.system.service.DataExceptionDetailService;
import com.lvy.hczn.front.system.service.DataExceptionService;
import com.lvy.hczn.front.system.service.ISysOperLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * DataExceptionService放错地方了，暂时新建ExceptionService处理
 *
 * @author yw
 * @date 2023-09-24 16:12:45
 **/
@Service
@Slf4j
public class ExceptionServiceImpl implements ExceptionService {

    @Autowired
    private PurchaseOrderDetailService purchaseOrderDetailService;

    @Autowired
    private PurchaseOrderService purchaseOrderService;

    @Autowired
    private DataExceptionService dataExceptionService;

    @Autowired
    private DataExceptionDetailService dataExceptionDetailService;

    @Autowired
    private DeliveryOrderDetailService deliveryOrderDetailService;

    @Autowired
    private WarehousingEntryService warehousingEntryService;

    @Autowired
    private AccessManagerService accessManagerService;

    @Autowired
    private MqttRecordService mqttRecordService;

    @Autowired
    private ISysJobLogService sysJobLogService;

    @Autowired
    private ISysOperLogService sysOperLogService;

    @Autowired
    private UpOrDownPolicyHistoryService upOrDownPolicyHistoryService;

    /**
     * 货箱缺失，配送时，货箱丢失的处理操作
     *
     * @param purchaseOrderDetail
     */
    @Override
    @Transactional
    public List<String> boxLost(PurchaseOrderDetail purchaseOrderDetail) throws Exception {
        List<String> ids = new ArrayList<>();
        if (StrUtil.isEmpty(purchaseOrderDetail.getPurchaseOrderCode())) {
            throw new UtilException("采购单号为空");
        }
        if (StrUtil.isEmpty(purchaseOrderDetail.getBoxCode())) {
            throw new UtilException("货箱编号为空");
        }
        if (StrUtil.isEmpty(purchaseOrderDetail.getClientId())) {
            throw new UtilException("客户端编号为空");
        }
        List<PurchaseOrderDetail> list = new ArrayList<>();
        /*大件商品单个物品缺失，非大件商品，整个货箱缺失**/
        if (!StrUtil.isEmpty(purchaseOrderDetail.getId()) && purchaseOrderDetail.getBigProduct().equals(com.lvy.hczn.front.common.constant.Constants.GOODS_COLLECT_YES)) {
            PurchaseOrderDetail purchaseOrderDetailInfo = purchaseOrderDetailService.getById(purchaseOrderDetail.getId());
            if (purchaseOrderDetailInfo == null) {
                throw new UtilException("商品采购信息为空");
            }
            list.add(purchaseOrderDetailInfo);
        } else {
            list = purchaseOrderDetailService.list(Wrappers.<PurchaseOrderDetail>lambdaQuery().eq(PurchaseOrderDetail::getPurchaseOrderCode, purchaseOrderDetail.getPurchaseOrderCode()).eq(PurchaseOrderDetail::getBoxCode, purchaseOrderDetail.getBoxCode()));
            if (list.isEmpty()) {
                throw new UtilException("数据为空");
            }
        }

        //好几个地方用到，后续提出来
        List<String> dataTypes = com.lvy.hczn.front.common.constant.Constants.entryDataTypeList();

        //货箱缺失
        PurchaseOrder purchaseOrder = purchaseOrderService.getOne(Wrappers.<PurchaseOrder>lambdaQuery().eq(PurchaseOrder::getPurchaseOrderCode, purchaseOrderDetail.getPurchaseOrderCode()));
        BigDecimal totalWeight = BigDecimal.ZERO;
        List<WarehousingEntry> entryList = new ArrayList<>();
        for (PurchaseOrderDetail item : list) {
            item.setStatus(Constants.ENTRY_LOSS);
            purchaseOrderDetailService.updateById(item);
            ids.add(item.getId());
            totalWeight = totalWeight.add(item.getPurchaseWeight());
            //初始化入库单
            generateEntry(item, purchaseOrder, entryList, dataTypes);
        }

        /**初始化异常数据**/
        List<DataException> dataExceptionList = dataExceptionService.list(Wrappers.<DataException>lambdaQuery().eq(DataException::getDeliveryCode, purchaseOrder.getPurchaseOrderCode()));
        DataException dataException = new DataException();
        if (dataExceptionList.isEmpty()) {
            dataException.setEntryCode(purchaseOrder.getPurchaseOrderCode());
            dataException.setDeliveryCode(purchaseOrder.getPurchaseOrderCode());
            dataException.setDeliveryType(purchaseOrder.getDeliveryType());
            dataException.setServiceCode(purchaseOrder.getServiceCode());
            dataException.setType(com.lvy.hczn.front.common.constant.Constants.DATA_EXCEPTION_ENTRY);
            dataException.setSync(false);
            dataExceptionService.save(dataException);
        } else {
            dataException = dataExceptionList.get(0);
        }
        DataExceptionDetail dataExceptionDetail = new DataExceptionDetail();
        dataExceptionDetail.setDataExceptionId(dataException.getId());
        dataExceptionDetail.setType(com.lvy.hczn.front.common.constant.Constants.DATA_EXCEPTION_DETAIL_LOST);
        dataExceptionDetail.setDataType(com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_SIX);
        dataExceptionDetail.setBoxCode(purchaseOrderDetail.getBoxCode());
        dataExceptionDetail.setPurchaseWeight(totalWeight);
        dataExceptionDetail.setActWeight(totalWeight);
        dataExceptionDetail.setSubWeight(dataExceptionDetail.getPurchaseWeight().subtract(dataExceptionDetail.getActWeight()));
        dataExceptionDetailService.save(dataExceptionDetail);

        if (!entryList.isEmpty()) {
            //保存入库单
            if (warehousingEntryService.updateBatchById(entryList)) {
                //校验入库单是否入库完成，入库完成则提交到平台
                Param param = new Param();
                param.setDeliveryOrderCode(purchaseOrder.getPurchaseOrderCode());
                UpOrDownPolicy upOrDownPolicy = new UpOrDownPolicy();
                upOrDownPolicy.setClientId(purchaseOrderDetail.getClientId());
                param.setUpOrDownPolicy(upOrDownPolicy);
                param.setBigProduct(purchaseOrderDetail.getBigProduct());
                deliveryOrderDetailService.entryByDeliverCode(param);
            }
        }


        return ids;
    }

    /**
     * 初始化缺货入库单
     *
     * @param detail
     * @param purchaseOrderInfo
     * @return void
     * @author yw
     * @date 2023-06-20 20:26:43
     */
    public void generateEntry(PurchaseOrderDetail detail, PurchaseOrder purchaseOrderInfo, List<WarehousingEntry> entryList, List<String> dataTypes) {
        List<WarehousingEntry> list = warehousingEntryService.list(Wrappers.<WarehousingEntry>lambdaQuery().eq(WarehousingEntry::getEntryCode, purchaseOrderInfo.getPurchaseOrderCode()).eq(WarehousingEntry::getServiceCode, purchaseOrderInfo.getServiceCode()).eq(WarehousingEntry::getSpuId, detail.getSpuId()).eq(WarehousingEntry::getSkuCode, detail.getSkuCode()).in(WarehousingEntry::getDataType, dataTypes));
        list.forEach(warehousingEntry -> {
            warehousingEntry.setPrice(BigDecimal.ZERO);
            warehousingEntry.setQuantity(0);
            warehousingEntry.setWeight(BigDecimal.ZERO);
            entryList.add(warehousingEntry);
        });

        /*WarehousingEntry warehousingEntry = new WarehousingEntry();
        warehousingEntry.setEntryCode(purchaseOrderInfo.getPurchaseOrderCode());
        warehousingEntry.setServiceCode(purchaseOrderInfo.getServiceCode());
        warehousingEntry.setWarehouseCode(purchaseOrderInfo.getWarehouseCode());
        warehousingEntry.setDataType(detail.getDataType());
        warehousingEntry.setBoxCode(detail.getBoxCode());
        warehousingEntry.setSourceId(detail.getSourceId());
        warehousingEntry.setServiceCode(purchaseOrderInfo.getServiceCode());
        warehousingEntry.setServiceType(purchaseOrderInfo.getServiceType());
        warehousingEntry.setOrderType(purchaseOrderInfo.getDeliveryType());
        warehousingEntry.setSpuId(detail.getSpuId());
        warehousingEntry.setSpecCode(detail.getSpecCode());
        warehousingEntry.setSkuCode(detail.getSkuCode());
        warehousingEntry.setWarrantyDate(detail.getWarrantyDate());
        warehousingEntry.setPrice(BigDecimal.ZERO);
        warehousingEntry.setQuantity(0);
        warehousingEntry.setWeight(BigDecimal.ZERO);
        warehousingEntry.setPurchaserId("");
        warehousingEntry.setUnit(detail.getUnit());
        warehousingEntry.setSupplierCode(detail.getSupplierCode());
        warehousingEntry.setProducerId(detail.getProducerId());
        if (detail.getProduceDate() != null && detail.getWarrantyDate() != null) {
            warehousingEntry.setShelfLife(detail.getProduceDate().plusDays(detail.getWarrantyDate()));
        }
        warehousingEntry.setPickTime(detail.getProduceDate());
        warehousingEntry.setBatchCode(detail.getBatchCode());
        warehousingEntry.setProvenance("");
        warehousingEntry.setStatus("0");
        warehousingEntry.setNumberOfPerBox(detail.getNumberOfPerBox());
        warehousingEntry.setWeightOfPerBox(detail.getWeightOfPerBox());
        warehousingEntry.setRemark("货箱缺失");
        entryList.add(warehousingEntry);*/
    }

    /**
     * @Description 数据清零，保留一定时间内的数据
     * @Param days，清理多少天以前的数据
     * @Author yw
     * @Date 2024/9/12 9:54
     * @Return
     **/
    @Override
    public void dataClean(String days) {
        if (!StrUtil.isEmpty(days) && NumberUtil.isInteger(days)) {
            LocalDateTime localDateTime = LocalDateTime.now();
            long longDays = Long.parseLong(days);
            LocalDateTime dateTime = localDateTime.plusDays(-longDays);
            log.error("数据清理：{}", LocalDateTimeUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));

            /*门禁数据清理**/
            AccessManager accessManager = new AccessManager();
            accessManager.setCreateTime(dateTime);
            accessManager.setUpdateTime(dateTime);
            accessManagerService.logicDelete(accessManager);

            /*WMS,WCS通信记录数据清理**/
            MqttRecord mqttRecord = new MqttRecord();
            mqttRecord.setCreateTime(dateTime);
            mqttRecord.setUpdateTime(dateTime);
            mqttRecordService.logicDelete(mqttRecord);

            /*定时任务调度日志数据清理**/
            SysJobLog sysJobLog = new SysJobLog();
            Map<String, Object> map = new HashMap<>();
            map.put("endTime", LocalDateTimeUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));
            sysJobLog.setParams(map);
            List<SysJobLog> list = sysJobLogService.selectJobLogList(sysJobLog);
            if (list != null && !list.isEmpty()) {
                List<Long> stringList = list.stream().map(SysJobLog::getJobLogId).collect(Collectors.toList());
                stringList.forEach(item -> {
                    sysJobLogService.deleteJobLogById(item);
                });
            }

            /*操作记录数据清理**/
            SysOperLog sysOperLog = new SysOperLog();
            Map<String, Object> mapOperation = new HashMap<>();
            mapOperation.put("endTime", LocalDateTimeUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));
            sysOperLog.setParams(mapOperation);
            List<SysOperLog> operLogList = sysOperLogService.selectOperLogList(sysOperLog);
            if (operLogList != null && !operLogList.isEmpty()) {
                long[] stringList = operLogList.stream().mapToLong(SysOperLog::getOperId).toArray();
                String[] strArr = Arrays.stream(stringList).mapToObj(String::valueOf).toArray(String[]::new);
                sysOperLogService.deleteOperLogByIdsOfArray(strArr);
            }

            /*历史指令数据清理**/
            UpOrDownPolicyHistory upOrDownPolicyHistory = new UpOrDownPolicyHistory();
            upOrDownPolicyHistory.setCreateTime(dateTime);
            upOrDownPolicyHistory.setUpdateTime(dateTime);
            upOrDownPolicyHistoryService.logicDataDelete(upOrDownPolicyHistory);
        }
    }

    public static void main(String[] args) {
        String days = "60";
        if (NumberUtil.isInteger(days)) {
            LocalDateTime localDateTime = LocalDateTime.now();
            long longDays = Long.parseLong(days);
            LocalDateTime dateTime = localDateTime.plusDays(-longDays);
            System.out.println("数据清理：" + LocalDateTimeUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));
        }
        long[] stringList = {1, 3, 5, 6, 7, 8, 9, 0, 56};
        String[] strArr = Arrays.stream(stringList).mapToObj(String::valueOf).toArray(String[]::new);
    }
}
